package banxi.ktv.hdao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;

public  abstract class GenericDaoImpl<T,ID extends Serializable> implements GenericDao<T, ID> {

	private Class<T> persistentClass;
	private Session session;
	
	
	/**
	 * Dao实现必须知道它用于哪些持久化类.在构造器中要使用Java反射(Java Reflection),来查找泛型参数T的类,
	 * 并把它保存在一个本地成员中.
	 */
	@SuppressWarnings("unchecked")
	public GenericDaoImpl() {
		super();
		this.persistentClass = (Class<T>)( (ParameterizedType) getClass().getGenericSuperclass() ).getActualTypeArguments()[0];
	}
	
	
	public Class<T> getPersistentClass() {
		return persistentClass;
	}
	public void setPersistentClass(Class<T> persistentClass) {
		this.persistentClass = persistentClass;
	}
	public Session getSession() {
		if(session == null){
			session = HibernateHelper.getSession();
		}
		return session;
	}
	public void setSession(Session session) {
		this.session = session;
	}
	
	
	
	
	@SuppressWarnings("unchecked")
	public T findById(ID id, boolean lock) {
	   T entity;
	   if(lock){
		   entity = (T)getSession().load(getPersistentClass(), id,LockOptions.UPGRADE);
	   }else{
		   entity = (T) getSession().load(getPersistentClass(), id);
	   }
		return entity;
	}
	
	public List<T> findAll() {
		return findByCriteria();
	}

	@SuppressWarnings("unchecked")
	public List<T> findByExample(T example, String... exclude) {
		Criteria  criteria = getSession().createCriteria(getPersistentClass());
		Example aExample = Example.create(example);
		for(String name: exclude){
			aExample.excludeProperty(name);
		}
		criteria.add(aExample);
		return criteria.list();
	}
	
	public T makePersistent(T entity) {
		getSession().saveOrUpdate(entity);
		return entity;
	}
	public void makeTransient(T entity) {
		getSession().delete(entity);
	}
	public void flush() {
		getSession().flush();
		
	}
	public void clear() {
		getSession().clear();
		
	}
	
	@SuppressWarnings("unchecked")
	protected List<T> findByCriteria(Criterion...criterion) {
		Criteria criteria = getSession().createCriteria(getPersistentClass());
		for(Criterion c:criterion){
			criteria.add(c);
		}
		return criteria.list();
	}
	
	
}
